package com.ruoyi.framework.web.service;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.*;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.DeviceType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.config.WxMiniAppConfigProperties;
import com.ruoyi.system.domain.PaWxUser;
import com.ruoyi.system.domain.vo.PaWxUserVo;
import com.ruoyi.system.service.IPaWxUserService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;

/**
 * @ClassName WxLoginService
 * @Description 微信小程序相关操作
 * @date 2024/7/12 8:32
 * @Version 1.0
 * @Auther: zhangzhenyu
 */
@Component
@Slf4j
public class WxMiniAppLoginService {


    private static final String TOKEN_API_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
    private static final String PHONE_INFO_API_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={0}";

    private static final String JSCODE2SESSION = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";

    @Autowired
    private IPaWxUserService paWxUserService;

    @Resource
    private WxMiniAppConfigProperties wxMiniAppConfigProperties;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private WxMaService wxMaService;

    /**
     * 拼接需要的参数
     * appid = AppID 你自己的微信小程序APPID
     * js_code = AppSecret 你自己的微信APP密钥
     * grant_type=authorization_code = code 微信官方提供的临时凭证
     */
    public PaWxUserVo login(String code) {

        try {
            Long userId = SecurityUtils.getUserId();
            if (userId != null) {
                PaWxUser paWxUser = paWxUserService.selectPaWxUserByWxUserId(userId);
                if (ObjectUtil.isNotNull(paWxUser)) {
                    PaWxUserVo paWxUserVo = getPaWxUserVo(paWxUser,false);
                    return paWxUserVo;
                }
            }
        } catch (Exception e) {
            log.info("首次登录没有token");
        }
        try {
            WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
//            String openid = "pinzhuang2";
            String openid = session.getOpenid();
            /**先通过openid来查询是否存在*/
            PaWxUser paWxUser = paWxUserService.selectpaWxUserOpenID(openid);
            if (paWxUser == null) {
                /**如果不存在就插入到我们的数据库里*/
                PaWxUser wxuser = new PaWxUser();
                wxuser.setOpenId(openid);
                wxuser.setCreateTime(DateUtils.getNowDate());
//                wxuser.setNickname(paWxUser.getNickname());
                wxuser.setUserType(DeviceType.XCX.getDevice());
                wxuser.setUnionid(session.getUnionid());
                paWxUserService.insertPaWxUser(wxuser);
                /**返回结果集到前段*/
                PaWxUserVo paWxUserVo = getPaWxUserVo(wxuser,true);
                return paWxUserVo;
            } else {
                /**返回结果集到前段*/
                PaWxUserVo paWxUserVo = getPaWxUserVo(paWxUser,true);
                return paWxUserVo;
            }
        } catch (Exception e) {
            log.info("获取用户信息失败 e={}",e);
            return null;
        }
    }


    /**
     * 保存用户信息
     * @param param
     * @return
     */
    public R saveInfo(PaWxUser param) {
        PaWxUser pswxUser =  paWxUserService.selectPaWxUserByWxUserId(param.getWxUserId());
        if (ObjectUtil.isNull(pswxUser)) {
            return R.fail("授权有误");
        }
        pswxUser.setNickname(param.getNickname());
        pswxUser.setAvatarUrl(param.getAvatarUrl());
        pswxUser.setPhone(param.getPhone());
        paWxUserService.updatePaWxUser(pswxUser);
        PaWxUserVo paWxUserVo = getPaWxUserVo(pswxUser, false);
        return R.ok(paWxUserVo);
    }

    /**
     * 获取手机号方法
     * @param code
     * @return
     */
    public String fetchPhoneInfo(String code) {
     /*   String accessToken = fetchAccessToken();
        if (StrUtil.isNotBlank(accessToken)) {
            return fetchPhoneInfoWithAccessToken(accessToken, code);
        }*/
        try {
            WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(code);
            return phoneNoInfo.getPhoneNumber();
        } catch (Exception e) {
            log.info("公众号获取手机号出错={}",  e);
        }
        return null;
    }

    private String fetchAccessToken() {
        String url = StrUtil.format(TOKEN_API_URL, wxMiniAppConfigProperties.getAppid(), wxMiniAppConfigProperties.getSecret());
        String response = HttpUtil.get(url);
        JSONObject jsonToken = JSONUtil.parseObj(response);
        return jsonToken.getStr("access_token");
    }

    private String fetchPhoneInfoWithAccessToken(String accessToken, String code) {
        String url = StrUtil.format(PHONE_INFO_API_URL, accessToken);
        HashMap<String, Object> requestParam = new HashMap<>();
        requestParam.put("code", code);
        String jsonStr = JSONUtil.toJsonStr(requestParam);

        HttpResponse response = HttpRequest.post(url)
                .header(Header.CONTENT_TYPE, "application/json")
                .body(jsonStr)
                .execute();

        if (response.isOk()) {
            return response.body();
        }
        return null;
    }


    private PaWxUserVo getPaWxUserVo(PaWxUser paWxUser, Boolean isNewLogin) {
        PaWxUserVo paWxUserVo = new PaWxUserVo();
        if (isNewLogin) {
            LoginUser loginUser = new LoginUser();
            loginUser.setUserId(paWxUser.getWxUserId());
            loginUser.setOpendId(paWxUser.getOpenId());
            loginUser.setNickName(paWxUser.getNickname());
            SysUser user = new SysUser();
            user.setUserId(paWxUser.getWxUserId());
            user.setUserName(paWxUser.getNickname());
            user.setPhonenumber(paWxUser.getPhone());
            loginUser.setUser(user);
            paWxUserVo.setToken(tokenService.createToken(loginUser));
        } else {
            LoginUser loginUser = SecurityUtils.getLoginUser();
            loginUser.setOpendId(paWxUser.getOpenId());
            loginUser.setNickName(paWxUser.getNickname());
            loginUser.getUser().setUserName(paWxUser.getNickname());
            paWxUserVo.setToken(SecurityUtils.getLoginUser().getUseToken());
            tokenService.refreshToken(loginUser);
        }
        paWxUserVo.setPaWxUser(paWxUser);
        return paWxUserVo;
    }

}
